/**
 * Copyright (c) 2020 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * https://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 */
package org.eclipse.vorto.codegen.openapi.templates

import org.eclipse.vorto.codegen.openapi.Utils
import org.eclipse.vorto.core.api.model.datatype.ConstraintIntervalType
import org.eclipse.vorto.core.api.model.datatype.ConstraintRule
import org.eclipse.vorto.core.api.model.datatype.ObjectPropertyType
import org.eclipse.vorto.core.api.model.datatype.PrimitivePropertyType
import org.eclipse.vorto.core.api.model.datatype.PrimitiveType
import org.eclipse.vorto.core.api.model.functionblock.Event
import org.eclipse.vorto.core.api.model.functionblock.FunctionblockModel
import org.eclipse.vorto.core.api.model.functionblock.Operation
import org.eclipse.vorto.core.api.model.functionblock.PrimitiveParam
import org.eclipse.vorto.core.api.model.functionblock.RefParam
import org.eclipse.vorto.core.api.model.functionblock.ReturnObjectType
import org.eclipse.vorto.core.api.model.functionblock.ReturnPrimitiveType
import org.eclipse.vorto.core.api.model.informationmodel.InformationModel
import org.eclipse.vorto.plugin.generator.InvocationContext
import org.eclipse.vorto.plugin.generator.utils.IFileTemplate

/**
 * Creates an OpenAPI v3 Specification for an Information Model. Supports configuration, status properties as well as operations
 * 
 */
class OpenAPITemplate implements IFileTemplate<InformationModel> {
			
	override getFileName(InformationModel model) {
		'''«model.name»-openapi-v3.yml'''
	}
	
	override getPath(InformationModel context) {
		return null
	}
	
	override getContent(InformationModel infomodel, InvocationContext context) {
		'''
		### Generated by Eclipse Vorto OpenAPI Generator from Model '«infomodel.namespace»:«infomodel.name»:«infomodel.version»'
		openapi: 3.0.0
		info:
		  title: Bosch IoT Things HTTP API for «infomodel.name» 
		  description: |-
		    Bosch IoT Things enables applications to manage digital twins of IoT device assets in a simple, convenient, robust, and secure way.
		    
		    These descriptions focus on the JSON-based, REST-like API of the <a href="https://vorto.eclipseprojects.io/#/details/«infomodel.namespace»:«infomodel.name»:«infomodel.version»">«infomodel.name»</a> Vorto Model.
		    
		    For more details on concepts, please consult the full [documentation](https://things.eu-1.bosch-iot-suite.com/dokuwiki/).
		  version: "«infomodel.version»"
		servers:
		  - url: https://things.eu-1.bosch-iot-suite.com/api/2
		    description: "Bosch IoT Things Service"
		tags:
		  - name: Things
		    description: Manage every Thing
		  - name: Features
		    description: Features of your «infomodel.name» things
		  - name: Things-Search
		    description: Find every Thing
		  - name: Messages
		    description: Send messages to / Receive event messages from «infomodel.name»
		security:
		  - bearerAuth: []
		paths:
		  ###
		  ### Things
		  ###
		  '/things':
		    get:
		      summary: Retrieve multiple Things with specified IDs
		      description: |-
		        Returns all things passed in by the required parameter `ids`, which you (the authorized subject) are allowed to read.
		      
		        Optionally, if you want to retrieve only some of the thing's fields, you can use the specific field selectors (see parameter `fields`) .
		      
		        Tip: If you don't know the thing IDs, start with the search resource.
		      tags:
		      - Things
		      parameters:
		      - name: ids
		        in: query
		        description: |-
		          Contains a comma-separated list of `thingId`s to retrieve in one single request.
		        required: true
		        schema:
		          type: string
		      - $ref: '#/components/parameters/thingFieldsQueryParam'
		      responses:
		          '200':
		            description: |-
		              The successfully completed request contains as its result the first 200 things, 
		              for which the user has at least read permission. The list is sorted by the `thingId`.
		            content:
		              application/json:
		                schema:
		                  type: array
		                  items:
		                    $ref: '#/components/schemas/Thing'
		          '400':
		            description: |-
		              The request could not be completed. At least one of the defined
		              query parameters was invalid.
		            content:
		              application/json:
		                schema:
		                  $ref: '#/components/schemas/AdvancedError'
		          '401':
		            description: The request could not be completed due to missing authentication.
		            content:
		              application/json:
		                schema:
		                  $ref: '#/components/schemas/AdvancedError'
		          '403':
		            description: |-
		              The request could not be completed due to a missing or invalid API
		              Token.
		            content:
		              application/json:
		                schema:
		                  $ref: '#/components/schemas/AdvancedError'
		          '414':
		            description: |-
		              The request could not be completed due to an URI length exceeding 8k
		              characters.
		  '/things/{thingId}':
		    get:
		      summary: Retrieve a specific Thing
		      description: |-
		        Returns the thing identified by the `thingId` path parameter. The
		        response includes details about the thing.
		        
		        Optionally, you can use the field selectors (see parameter `fields`) to only get specific
		        fields, which you are interested in.
		      tags:
		      - Things
		      parameters:
		      - $ref: '#/components/parameters/thingIdPathParam'
		      - $ref: '#/components/parameters/thingFieldsQueryParam'
		      - $ref: '#/components/parameters/ifMatchHeaderParam'
		      - $ref: '#/components/parameters/ifNoneMatchHeaderParam'
		      responses:
		          '200':
		            description: The request successfully returned the specific Thing.
		            headers:
		              ETag:
		                description: |-
		                  The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format
		                  "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]".
		                schema:
		                  type: string
		            content:
		              application/json:
		                schema:
		                  $ref: '#/components/schemas/Thing'
		          '304':
		            $ref: '#/components/responses/notModified'
		          '400':
		            description: |-
		              The request could not be completed. Possible reasons:
		            
		                * the `thingId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.org/ditto/basic-namespaces-and-names.html#namespaced-id))
		                * at least one of the defined query parameters is invalid
		            content:
		              application/json:
		                schema:
		                  $ref: '#/components/schemas/AdvancedError'
		          '401':
		            description: The request could not be completed due to missing authentication.
		            content:
		              application/json:
		                schema:
		                  $ref: '#/components/schemas/AdvancedError'
		          '403':
		            description: |-
		              The request could not be completed due to a missing or invalid API
		              Token.
		            content:
		              application/json:
		                schema:
		                  $ref: '#/components/schemas/AdvancedError'
		          '404':
		            description: |-
		              The request could not be completed. The Thing with the given ID was
		              not found.
		            content:
		              application/json:
		                schema:
		                  $ref: '#/components/schemas/AdvancedError'
		          '412':
		            $ref: '#/components/responses/preconditionFailed'
		  ###
		  ### Things-Search
		  ###
		  '/search/things':
		    get:
		      summary: Search for Things
		      description: |-
		        This resource can be used to search for things.
		        
		        * The query parameter `filter` is not mandatory. If it is not set, the
		          result contains all things which the logged in user is allowed to read.
		          
		        * The search is case sensitive. In case you don't know how exactly the
		          spelling of the namespace, name, attribute, feature etc. is, use the *like*
		          notation for filtering
		          
		        * The search result is limited to the things within the namespace (or namespaces)
		          the solution is configured for. You can explicitly search in specific namespaces
		          by including them in the query via the *namespaces* parameter.
		          
		        * The resource supports sorting and paging. If paging is not explicitly
		          specified by means of the `size` option, a default count of `25`
		          documents is returned.
		          
		        * The internal search index is "eventually consistent".  Consistency with the latest
		          thing updates should recover within milliseconds.
		          
		      parameters:
		      - $ref: '#/components/parameters/searchFilter'
		      - $ref: '#/components/parameters/namespacesFilter'
		      - $ref: '#/components/parameters/thingFieldsQueryParam'
		      - name: option
		        in: query
		        description: |-
		          Possible values for the parameter:
		          
		          #### Sort operations
		          
		          * ```sort([+|-]{property})```
		          * ```sort([+|-]{property},[+|-]{property},...)```
		          
		          #### Paging operations
		          
		          * ```size({page-size})```  Maximum allowed page size is `200`. Default page size is `25`.
		          * ```cursor({cursor-id})```  Start the search from the cursor location. Specify the cursor ID without
		          quotation marks. Cursor IDs are given in search responses and mark the position after the last entry of
		          the previous search. The meaning of cursor IDs is unspecified and may change without notice.
		          
		          The paging option `limit({offset},{count})` is deprecated.
		          It may result in slow queries or timeouts and will be removed eventually.
		          
		          #### Examples:
		          
		          * ```sort(+thingId)```
		          * ```sort(-attributes/manufacturer)```
		          * ```sort(+thingId,-attributes/manufacturer)```
		          * ```size(10)``` return 10 results
		          * ```cursor(LOREMIPSUM)```  return results after the position of the cursor `LOREMIPSUM`.
		          
		          #### Combine:
		          
		          If you need to specify multiple options, when using the swagger UI just write each option in a new line.
		          When using the plain REST API programmatically,
		          you will need to separate the options using a comma (,) character.
		          
		          ```size(200),cursor(LOREMIPSUM)```
		          
		          The deprecated paging option `limit` may not be combined with the other paging options `size` and `cursor`.
		        required: false
		        schema:
		          type: array
		          items:
		            type: string
		      tags:
		      - Things-Search
		      responses:
		        '200':
		          description: An array of the matching things.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/SearchResultThings'
		        '400':
		          description: |-
		            The request could not be completed. A provided parameter is in a
		            wrong format.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '401':
		          description: The request could not be completed due to missing authentication.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '403':
		          description: The request could not be completed due to an invalid authentication.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '504':
		          description: The request ran out of time to execute on the the back-end. Optimize your query and try again.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		  '/search/things/count':
		    get:
		      summary: Count Things
		      description: |-
		        This resource can be used to count things.
		        
		        The query parameter `filter` is not mandatory. If it is not set there is
		        returned the total amount of things which the logged in user is allowed
		        to read.
		        
		        To search for nested properties, we use JSON Pointer notation
		        (RFC-6901). See the following example how to search for the sub property
		        `location` of the parent property `attributes` with a forward slash as
		        separator:
		        
		        ```eq(attributes/location,"kitchen")```
		        
		        The search result is limited to the Things within the namespace (or namespaces) the solution is configured
		        for. You can explicitly search in other namespaces by including them in the query via the `namespaces`
		        parameter.
		        
		      parameters:
		      - $ref: '#/components/parameters/searchFilter'
		      - $ref: '#/components/parameters/namespacesFilter'
		      tags:
		      - Things-Search
		      responses:
		        '200':
		          description: A number indicating the amount of matched things
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/SearchResultThingsCount'
		        '400':
		          description: |-
		            The request could not be completed. A provided parameter is in a
		            wrong format.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '401':
		          description: The request could not be completed due to missing authentication.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '403':
		          description: The request could not be completed due to an invalid authentication.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '504':
		          description: The request ran out of time to execute on the the back-end. Optimize your query and try again.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		  ###
		  ### «infomodel.name» Features
		  ###
		  '/things/{thingId}/features':
		    get:
		      summary: List all features of a «infomodel.name» 
		      description: |-
		        Returns all features of the «infomodel.name» thing identified by the `thingId` path parameter.
		      tags:
		      - Features
		      parameters:
		      - $ref: '#/components/parameters/thingIdPathParam'
		      - $ref: '#/components/parameters/featuresFieldsQueryParam'
		      - $ref: '#/components/parameters/ifMatchHeaderParam'
		      - $ref: '#/components/parameters/ifNoneMatchHeaderParam'
		      responses:
		        '200':
		          description: |-
		            The list of features of the «infomodel.name» were successfully retrieved.
		          headers:
		            ETag:
		              description: |-
		                The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format
		                "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]".
		              schema:
		                type: string
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/«infomodel.name»Features'
		        '304':
		          $ref: '#/components/responses/notModified'
		        '400':
		          description: |-
		            The request could not be completed. The `thingId` either
		            
		              * does not contain the mandatory namespace prefix (java package notation + `:` colon)
		              * does not conform to RFC-2396 (URI)
		              
		            Or at least one of the defined query parameters was invalid.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '401':
		          description: The request could not be completed due to missing authentication.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '404':
		          description: |-
		            The request could not be completed. The Thing with the given ID was not found or the Features have not
		            been defined.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '412':
		          $ref: '#/components/responses/preconditionFailed'
		  «FOR fbProperty : infomodel.properties»
		  '/things/{thingId}/features/«fbProperty.name»':
		    get:
		      summary: Retrieve the «fbProperty.name» of the «infomodel.name»
		      description: |-
		        Returns the specific feature `«fbProperty.name»`
		        of the thing identified by the `thingId` path parameter.
		      tags:
		      - Features
		      parameters:
		      - $ref: '#/components/parameters/thingIdPathParam'
		      - $ref: '#/components/parameters/featureFieldsQueryParam'
		      - $ref: '#/components/parameters/ifMatchHeaderParam'
		      - $ref: '#/components/parameters/ifNoneMatchHeaderParam'
		      responses:
		        '200':
		          description: The «fbProperty.name» was successfully retrieved.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/«fbProperty.type.name»Feature'
		        '304':
		          $ref: '#/components/responses/notModified'
		        '400':
		          description: |-
		            The request could not be completed. The `thingId` either
		              * does not contain the mandatory namespace prefix (java package notation + `:` colon)
		              * does not conform to RFC-2396 (URI)
		            Or at least one of the defined query parameters was invalid.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '401':
		          description: The request could not be completed due to missing authentication.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '404':
		          description: |-
		            The request could not be completed. The Thing with the given ID or the Feature with the specified
		            `featureId` was not found.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '412':
		          $ref: '#/components/responses/preconditionFailed'
		  '/things/{thingId}/features/«fbProperty.name»/properties':
		    get:
		      summary: Retrieve the properties of «fbProperty.name»
		      description: |-
		        Returns all properties of the feature `«fbProperty.name»` identified by the `thingId` path parameter.
		      tags:
		      - Features
		      parameters:
		      - $ref: '#/components/parameters/thingIdPathParam'
		      - $ref: '#/components/parameters/propertiesFieldsQueryParam'
		      - $ref: '#/components/parameters/ifMatchHeaderParam'
		      - $ref: '#/components/parameters/ifNoneMatchHeaderParam'
		      responses:
		        '200':
		          description: The «fbProperty.name» was successfully retrieved.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/«fbProperty.type.name»Properties'
		        '304':
		          $ref: '#/components/responses/notModified'
		        '400':
		          description: |-
		            The request could not be completed. The `thingId` either
		              * does not contain the mandatory namespace prefix (java package notation + `:` colon)
		              * does not conform to RFC-2396 (URI)
		            Or at least one of the defined query parameters was invalid.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '401':
		          description: The request could not be completed due to missing authentication.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '404':
		          description: |-
		            The request could not be completed. The Thing with the given ID or the Feature with the specified
		            `featureId` was not found.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '412':
		          $ref: '#/components/responses/preconditionFailed'
		  '/things/{thingId}/features/«fbProperty.name»/properties/{propertyPath}':
		    get:
		      summary: Retrieve a specific property of «fbProperty.name»
		      description: |-
		        Returns the specific property path of the feature `«fbProperty.name»` identified by the `thingId` path parameter.
		        	
		        The property (JSON) can be referenced
		        hierarchically, by applying JSON Pointer notation (RFC-6901)
		      tags:
		      - Features
		      parameters:
		      - $ref: '#/components/parameters/thingIdPathParam'
		      - $ref: '#/components/parameters/propertyPathPathParam'
		      - $ref: '#/components/parameters/ifMatchHeaderParam'
		      - $ref: '#/components/parameters/ifNoneMatchHeaderParam'
		      responses:
		        '200':
		          description: The Property was successfully retrieved.
		          headers:
		            ETag:
		              description: |-
		                The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format
		                "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]".
		              schema:
		                type: string
		        '304':
		          $ref: '#/components/responses/notModified'
		        '400':
		          description: |-
		            The request could not be completed. The `thingId` either
		              * does not contain the mandatory namespace prefix (java package notation + `:` colon)
		              * does not conform to RFC-2396 (URI)
		            Or at least one of the defined query parameters was invalid.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '401':
		          description: The request could not be completed due to missing authentication.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '404':
		          description: |-
		            The request could not be completed. The Thing with the given ID or the Feature with the specified
		            `featureId` was not found.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '412':
		          $ref: '#/components/responses/preconditionFailed'		          
		  «IF fbProperty.type.functionblock.configuration !== null && !fbProperty.type.functionblock.configuration.properties.empty»
		  «FOR configurationProperty : fbProperty.type.functionblock.configuration.properties»
		  '/things/{thingId}/features/«fbProperty.name»/properties/configuration/«configurationProperty.name»':
		    put:
		      summary: Sets the device configuration property «configurationProperty.name» of the «fbProperty.name» feature
		      description: |-
		        Sets the «configurationProperty.name» of the «fbProperty.name» feature, identified by the
		        `thingId` path parameter. The set configuration property is transmitted to the device, once the device is connected.
		      tags:
		        - Features
		      parameters:
		        - $ref: '#/components/parameters/thingIdPathParam'
		      responses:
		        '204':
		          description: The Property was successfully updated.
		        '400':
		          description: |-
		            The request could not be completed. The `thingId` either
		              * does not contain the mandatory namespace prefix (java package notation + `:` colon)
		              * does not conform to RFC-2396 (URI)
		            Or the JSON was invalid.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '401':
		          description: The request could not be completed due to missing authentication.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '402':
		          description: The request could not be completed due to exceeded data volume.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '403':
		          description: |-
		            The request could not be completed. Either
		              * due to a missing or invalid API Token.
		              * as the caller had insufficient permissions.
		            For creating/updating a Property of an existing Feature `WRITE` permission is required.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '404':
		          description: |-
		              The request could not be completed. The Thing or the Feature with
		              the given ID was not found.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '412':
		          $ref: '#/components/responses/preconditionFailed'
		        '413':
		          $ref: '#/components/responses/entityTooLarge'
		      requestBody:
		        $ref: '#/components/requestBodies/«fbProperty.type.name»«configurationProperty.name.toFirstUpper»ConfigurationValue'
		  «ENDFOR»
		  «ENDIF»
		  ###
		  ### Messages
		  ###
		  «FOR event : fbProperty.type.functionblock.events»
		  '/things/{thingId}/features/«fbProperty.name»/outbox/messages/«event.name»':
		    post:
		      summary: Send a message FROM a specific Feature `«fbProperty.name»` of a specific Thing.
		      description: |-
		        Send a message with the subject `«event.name»` **from** the feature
		        specified by the featureId `«fbProperty.name»` and `thingId` path parameter. The request
		        body contains the message payload and the `Content-Type` header defines
		        its type.
		        
		        The HTTP request blocks until a response to the message is available
		        or until the `timeout` is expired. If many clients respond to
		        the issued message, the first response will complete the HTTP request.
		        
		        In order to handle the message in a fire and forget manner, add
		        a query-parameter `timeout=0` to the request.
		        
		        ### Who
		        You will need `WRITE` permission on the root "message:/" resource, or at least
		        the resource `message:/features/featureId/outbox/messages/messageSubject`.
		        Such permission is managed  within the policy which controls the access on the thing.
		      tags:
		        - Messages
		      parameters:
		      - $ref: '#/components/parameters/thingIdPathParam'
		      - $ref: '#/components/parameters/messageTimeoutParam'
		      responses:
		        '202':
		          description: The message was sent (fire and forget).
		        '400':
		          description: |-
		            The request could not be completed. The `thingId` either
		            * does not contain the mandatory namespace prefix (java package notation + `:` colon)
		            * does not conform to RFC-2396 (URI)
		            
		            Or at least one of the defined path parameters was invalid.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '401':
		          description: The request could not be completed due to missing authentication.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '403':
		          description: |-
		            The request could not be completed. Either
		            * due to a missing or invalid API Token.
		            * as the caller does not have `WRITE` permission on the resource message:/outbox/messages/`messageSubject`.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '413':
		          $ref: '#/components/responses/messageTooLarge'
		      «IF !event.properties.empty»
		      requestBody:
		        $ref: '#/components/requestBodies/«fbProperty.type.name»«event.name.toFirstUpper»EventPayload'
		      «ENDIF»
		  «ENDFOR»
		  «FOR operation : fbProperty.type.functionblock.operations»
		  '/things/{thingId}/features/«fbProperty.name»/inbox/messages/«operation.name»':
		    post:
		      summary: Executes the «operation.name» on the device
		      description: |-
		        «IF operation.description !== null»«operation.description»«ELSE»Executes the «operation.name» on the device.«ENDIF»
		      
		        Send a message with the messageSubject `«operation.name»` **to** the feature specified by the featureId `«fbProperty.name»` 
		        and thingId path parameter. The request body contains the message payload and the Content-Type header defines its type. 
		        The API does not provide any kind of acknowledgement that the message was received by the feature.
		        
		        The HTTP request blocks until a response to the message is available
		        or until the `timeout` is expired. If many clients respond to
		        the issued message, the first response will complete the HTTP request.
		        
		        In order to handle the message in a fire and forget manner, add
		        a query-parameter `timeout=0` to the request.
		        
		        ### Who
		        You will need `WRITE` permission on the root "message:/" resource, or at least
		        the resource `message:/outbox/messages/messageSubject`.
		        Such permission is managed  within the policy which controls the access on the thing.
		      tags:
		        - Messages
		      parameters:
		        - $ref: '#/components/parameters/thingIdPathParam'
		        - $ref: '#/components/parameters/messageTimeoutParam'
		      responses:
		        '202':
		          description: |-
		            The message was sent but not necessarily received by the Feature
		            (fire and forget).
		          «IF operation.returnType !== null»
		          content:
		            application/json:
		              schema:
		                «IF operation.returnType instanceof ReturnPrimitiveType»
		                «wrapIfMultiple(getPrimitive((operation.returnType as ReturnPrimitiveType).returnType).toString,(operation.returnType as ReturnPrimitiveType).multiplicity)»
		                «ELSEIF operation.returnType instanceof ReturnObjectType»
		                «wrapIfMultiple("$ref: '#/components/schemas/"+(operation.returnType as ReturnObjectType).returnType.name+"'",(operation.returnType as ReturnObjectType).multiplicity)»
		                «ENDIF»
		          «ENDIF»
		        '400':
		          description: |-
		            The request could not be completed. Possible reasons:
		              * the `thingId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.org/ditto/basic-namespaces-and-names.html#namespaced-id)).
		              * at least one of the defined path parameters is invalid.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '401':
		          description: The request could not be completed due to missing authentication.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '403':
		          description: |-
		            The request could not be completed. Possible reasons:
		            	
		            * the API Token is missing or invalid
		            * the caller has insufficient permissions
		              You need `WRITE` permission on the resource `message:/features/{featureId}/inbox/messages/{messageSubject}`.
		          content:
		            application/json:
		              schema:
		                $ref: '#/components/schemas/AdvancedError'
		        '413':
		          $ref: '#/components/responses/messageTooLarge'
		      «IF !operation.params.empty»
		      requestBody:
		        $ref: '#/components/requestBodies/«fbProperty.type.name»«operation.name.toFirstUpper»Payload'
		      «ENDIF»
		  «ENDFOR»
		«ENDFOR»
		components:
		  schemas:
		    AdvancedError:
		      properties:
		        status:
		          type: integer
		          description: The HTTP status of the error
		        error:
		          type: string
		          description: The error code of the occurred exception
		        message:
		          type: string
		          description: The message of the error - what went wrong
		        description:
		          type: string
		          description: A description how to fix the error or more details
		        href:
		          type: string
		          description: A link to further information about the error and how to fix it
		      required:
		      - status
		      - error
		      - message
		    Thing:
		      type: object
		      required:
		      - thingId
		      - policyId
		      - attributes
		      - features
		      properties:
		        thingId:
		          type: string
		          description: Unique identifier representing the thing
		        policyId:
		          type: string
		          description: The policy ID used for controlling access to this thing, managed by resource `/policies/{policyId}`
		        attributes:
		          $ref: '#/components/schemas/Attributes'
		        features:
		          $ref: '#/components/schemas/«infomodel.name»Features'
		    Attributes:
		      type: object
		      description: An arbitrary JSON object describing the attributes of a Thing.
		    SearchResultThings:
		      properties:
		        items:
		          type: array
		          items:
		            $ref: '#/components/schemas/Thing'
		        cursor:
		          type: string
		    SearchResultThingsCount:
		      type: integer
		    FeatureDefinition:
		      type: array
		      minItems: 1
		      uniqueItems: true
		      items:
		        type: string
		        description: "A single fully qualified identifier of a Feature Definition in the form 'namespace:name:version'"
		        pattern: ([_a-zA-Z0-9\-.]+):([_a-zA-Z0-9\-.]+):([_a-zA-Z0-9\-.]+)
		    «FOR fb : Utils.getReferencedFunctionBlocks(infomodel)»
		    «IF fb.functionblock.configuration !== null»
		    «FOR configurationProperty : fb.functionblock.configuration.properties»
		    «fb.name»«configurationProperty.name.toFirstUpper»ConfigurationValue:
		      «IF configurationProperty.type instanceof PrimitivePropertyType»
		      «wrapIfMultiple(getPrimitive((configurationProperty.type as PrimitivePropertyType).type).toString,configurationProperty.multiplicity)»
		      «IF configurationProperty.constraintRule !== null»
		      «handleConstraints(configurationProperty.constraintRule)»
		      «ENDIF»
		      «ELSEIF configurationProperty.type instanceof ObjectPropertyType»
		      «wrapIfMultiple("$ref: '#/components/schemas/"+(configurationProperty.type as ObjectPropertyType).type.name+"'",configurationProperty.multiplicity)»
		      «ENDIF»
		    «ENDFOR»
		    «ENDIF»
		    «FOR operation : fb.functionblock.operations»
		    «IF !operation.params.empty»
		    «fb.name»«operation.name.toFirstUpper»Payload:
		      type: object
		      properties:
		        «FOR param : operation.params»
		        «param.name»:
		          «IF param.description !== null»description: «param.description»«ENDIF»
		          «IF param instanceof PrimitiveParam»
		          «wrapIfMultiple(getPrimitive((param as PrimitiveParam).type).toString,param.multiplicity)»
		          «IF param.constraintRule !== null»
		          «handleConstraints(param.constraintRule)»
		          «ENDIF»
		          «ELSEIF param instanceof RefParam»
		          «wrapIfMultiple("$ref: '#/components/schemas/"+(param as RefParam).type.name+"'",param.multiplicity)»
		          «ENDIF»
		        «ENDFOR»
		    «ENDIF»
		    «ENDFOR»
		    «fb.name»Properties:
		      type: object
		      description: «fb.name» properties of «infomodel.name»
		      «IF (fb.functionblock.status !== null && !fb.functionblock.status.properties.isEmpty) || 
		      	  (fb.functionblock.configuration !== null && !fb.functionblock.configuration.properties.isEmpty)»
		      properties:
		      «ENDIF»
		        «IF fb.functionblock.status !== null && !fb.functionblock.status.properties.isEmpty»
		        status:
		          type: object
		          properties:
		            «FOR statusProperty : fb.functionblock.status.properties»
		            «statusProperty.name»:
		              «IF statusProperty.description !== null»description: «statusProperty.description»«ENDIF»
		              «IF statusProperty.type instanceof PrimitivePropertyType»
		              «wrapIfMultiple(getPrimitive((statusProperty.type as PrimitivePropertyType).type).toString,statusProperty.multiplicity)»
		              «IF statusProperty.constraintRule !== null»
		              «handleConstraints(statusProperty.constraintRule)»
		              «ENDIF»
		              «ELSEIF statusProperty.type instanceof ObjectPropertyType»
		              «wrapIfMultiple("$ref: '#/components/schemas/"+(statusProperty.type as ObjectPropertyType).type.name+"'",statusProperty.multiplicity)»
		            «ENDIF»
		            «ENDFOR»
		          «Utils.calculateRequired(fb.functionblock.status.properties)»
		        «ENDIF»
		        «IF fb.functionblock.configuration !== null && !fb.functionblock.configuration.properties.isEmpty»
		        configuration:
		          type: object
		          properties:
		            «FOR configProperty : fb.functionblock.configuration.properties»
		            «configProperty.name»:
		              «IF configProperty.description !== null»description: «configProperty.description»«ENDIF»
		              «IF configProperty.type instanceof PrimitivePropertyType»
		              «wrapIfMultiple(getPrimitive((configProperty.type as PrimitivePropertyType).type).toString,configProperty.multiplicity)»
		              «IF configProperty.constraintRule !== null»
		              «handleConstraints(configProperty.constraintRule)»
		              «ENDIF»
		              «ELSEIF configProperty.type instanceof ObjectPropertyType»
		              «wrapIfMultiple("$ref: '#/components/schemas/"+(configProperty.type as ObjectPropertyType).type.name+"'",configProperty.multiplicity)»
		            «ENDIF»
		            «ENDFOR»
		          «Utils.calculateRequired(fb.functionblock.configuration.properties)»
		        «ENDIF»
		    «fb.name»Feature:
		      type: object
		      properties:
		        definition:
		          $ref: '#/components/schemas/FeatureDefinition'
		          description: The Definition of this «fb.name» Feature
		        properties:
		          $ref: '#/components/schemas/«fb.name»Properties'
		          description: The Properties of this «fb.name» feature
		    «ENDFOR»
		    «infomodel.name»Features:
		      type: object
		      description: |-
		        List all Features of the «infomodel.name»
		      properties:
		        «FOR fbProperty : infomodel.properties»
		        «fbProperty.name»:
		          «IF fbProperty.description !== null»description: «fbProperty.description»«ENDIF»
		          allOf:
		            - $ref: '#/components/schemas/«fbProperty.type.name»Feature'
		        «ENDFOR»
		    «FOR entity : Utils.getReferencedEntities(infomodel)»
		    «entity.name»:
		      type: object
		      properties:
		        «FOR property : entity.properties»
		        «property.name»:
		          «IF property.description !== null»description: «property.description»«ENDIF»
		          «IF property.type instanceof PrimitivePropertyType»
		          «wrapIfMultiple(getPrimitive((property.type as PrimitivePropertyType).type).toString,property.multiplicity)»
		          «IF property.constraintRule !== null»
		          «handleConstraints(property.constraintRule)»
		          «ENDIF»
		          «ELSEIF property.type instanceof ObjectPropertyType»
		          «wrapIfMultiple("$ref: '#/components/schemas/"+(property.type as ObjectPropertyType).type.name+"'",property.multiplicity)»
		          «ENDIF»
		        «ENDFOR»
		      «Utils.calculateRequired(entity.properties)»
		    «ENDFOR»
		    «FOR enumeration : Utils.getReferencedEnums(infomodel)»
		    «enumeration.name»:
		      type: string
		      enum: [«FOR literal: enumeration.enums SEPARATOR ','»«literal.name»«ENDFOR»]
		    «ENDFOR»
		  
		  «IF hasRequestBodiesContent(infomodel)»requestBodies:«ENDIF»
		    «FOR fb : Utils.getReferencedFunctionBlocks(infomodel)»
		    «FOR event : fb.functionblock.events»
		    «IF !event.properties.empty»
		    «fb.name»«event.name.toFirstUpper»EventPayload:
		      content:
		        application/json:
		          schema:
		            type: object
		            properties:
		              «FOR eventProperty : event.properties»
		              «eventProperty.name»:
		                «IF eventProperty.description !== null»description: «eventProperty.description»«ENDIF»
		                «IF eventProperty.type instanceof PrimitivePropertyType»
		                «wrapIfMultiple(getPrimitive((eventProperty.type as PrimitivePropertyType).type).toString,eventProperty.multiplicity)»
		                «IF eventProperty.constraintRule !== null»
		                «handleConstraints(eventProperty.constraintRule)»
		                «ENDIF»
		                «ELSEIF eventProperty.type instanceof ObjectPropertyType»
		                «wrapIfMultiple("$ref: '#/components/schemas/"+(eventProperty.type as ObjectPropertyType).type.name+"'",eventProperty.multiplicity)»
		                «ENDIF»
		              «ENDFOR»
		            «Utils.calculateRequired(event.properties)»
		    «ENDIF»
		    «ENDFOR»
		    «IF fb.functionblock.configuration !== null»
		      «FOR configurationProperty : fb.functionblock.configuration.properties»
		        «fb.name»«configurationProperty.name.toFirstUpper»ConfigurationValue:
		          content:
		            application/json:
		              schema:
		                «IF configurationProperty.type instanceof PrimitivePropertyType»
		                «wrapIfMultiple(getPrimitive((configurationProperty.type as PrimitivePropertyType).type).toString,configurationProperty.multiplicity)»
		                «IF configurationProperty.constraintRule !== null»
		                «handleConstraints(configurationProperty.constraintRule)»
		                «ENDIF»
		                «ELSEIF configurationProperty.type instanceof ObjectPropertyType»
		                «wrapIfMultiple("$ref: '#/components/schemas/"+(configurationProperty.type as ObjectPropertyType).type.name+"'",configurationProperty.multiplicity)»
		                «ENDIF»
		      «ENDFOR»
		    «ENDIF»
		    «FOR operation : fb.functionblock.operations»
		    «IF !operation.params.empty»
		    «fb.name»«operation.name.toFirstUpper»Payload:
		      content:
		        application/json:
		          schema:
		            type: object
		            properties:
		              «FOR param : operation.params»
		              «param.name»:
		                «IF param.description !== null»description: «param.description»«ENDIF»
		                «IF param instanceof PrimitiveParam»
		                «wrapIfMultiple(getPrimitive((param as PrimitiveParam).type).toString,param.multiplicity)»
		                «IF param.constraintRule !== null»
		                «handleConstraints(param.constraintRule)»
		                «ENDIF»
		                «ELSEIF param instanceof RefParam»
		                «wrapIfMultiple("$ref: '#/components/schemas/"+(param as RefParam).type.name+"'",param.multiplicity)»
		                «ENDIF»
		              «ENDFOR»
		    «ENDIF»
		    «ENDFOR»
		  «ENDFOR»
		  responses:
		    entityTooLarge:
		      description: |-
		        The created or modified entity is larger than the accepted limit of 100 kB.
		      content:
		        application/json:
		          schema:
		            $ref: '#/components/schemas/AdvancedError'
		    messageTooLarge:
		      description: |-
		        The size of the send message is larger than the accepted limit of 250 kB.
		      content:
		        application/json:
		          schema:
		            $ref: '#/components/schemas/AdvancedError'
		    notModified:
		      description: |-
		        The (sub-)resource has not been modified. This happens when you specified a If-None-Match header which
		        matches the current ETag of the (sub-)resource.
		      headers:
		        ETag:
		          description: |-
		            The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format
		            "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]".
		          schema:
		            type: string
		    preconditionFailed:
		      description: |-
		        A precondition for reading or writing the (sub-)resource failed. This will happen for write requests, when you
		        specified an If-Match or If-None-Match header which fails the precondition check against the current ETag of
		        the (sub-)resource. For read requests, this error may only happen for a failing If-Match header. In case of a
		        failing If-None-Match header for a read request, status 304 will be returned instead.
		      headers:
		        ETag:
		          description: |-
		            The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format
		            "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]".
		          schema:
		            type: string
		      content:
		        application/json:
		          schema:
		            $ref: '#/components/schemas/AdvancedError'
		  parameters:
		    ifMatchHeaderParam:
		      name: If-Match
		      in: header
		      description:  |-
		        The `If-Match` header, which has to conform to RFC-7232 (Conditional Requests). Common usages are:
		          * optimistic locking by specifying the `ETag` from a previous GET response, e.g. `If-Match: "rev:4711"`
		          * retrieving or modifying a resource only if it already exists, e.g. `If-Match: *`
		      required: false
		      schema:
		        type: string
		    ifNoneMatchHeaderParam:
		      name: If-None-Match
		      in: header
		      description:  |-
		        The `If-None-Match` header, which has to conform to RFC-7232 (Conditional Requests). A common usage scenario is to
		        modify a resource only if it does not yet exist, thus to create it, by specifying `If-None-Match: *`.
		      required: false
		      schema:
		        type: string
		    messageTimeoutParam:
		      name: timeout
		      in: query
		      description: |-
		          Contains an optional timeout (in seconds) of how long to wait for the message response and therefore block the
		          HTTP request. Default value (if omitted): 10 seconds. Maximum value: 60 seconds. A value of 0 seconds applies
		          fire and forget semantics for the message.
		      required: false
		      schema:
		        type: integer
		    thingIdPathParam:
		      name: thingId
		      in: path
		      description: |-
		        The ID of a thing needs to follow the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.org/ditto/basic-namespaces-and-names.html#namespaced-id)).
		        
		        The namespace needs to be registered for your solution.
		      required: true
		      schema:
		        type: string
		    propertyPathPathParam:
		      name: propertyPath
		      in: path
		      description: The path to the Property
		      required: true
		      schema:
		        type: string
		    thingFieldsQueryParam:
		      name: fields
		      in: query
		      description: |-
		        Contains a comma-separated list of fields to be included in the returned
		        JSON. Attributes can be selected in the same manner.
		        
		        #### Selectable fields
		        
		        * `thingId`
		        * `policyId`
		        * `attributes`
		        
		           Supports selecting arbitrary sub-fields by using a comma-separated list:
		            * several attribute paths can be passed as a comma-separated list of JSON pointers (RFC-6901)
		            
		              For example:
		                * `?fields=attributes/model` would select only `model` attribute value (if present)
		                * `?fields=attributes/model,attributes/location` would select only `model` and
		                   `location` attribute values (if present)
		                   
		          Supports selecting arbitrary sub-fields of objects by wrapping sub-fields inside parentheses `( )`:
		            * a comma-separated list of sub-fields (a sub-field is a JSON pointer (RFC-6901)
		              separated with `/`) to select
		              
		            * sub-selectors can be used to request only specific sub-fields by placing expressions
		              in parentheses `( )` after a selected subfield
		              
		              For example:
		               * `?fields=attributes(model,location)` would select only `model`
		                  and `location` attribute values (if present)
		               * `?fields=attributes(coffeemaker/serialno)` would select the `serialno` value
		                  inside the `coffeemaker` object
		               * `?fields=attributes/address/postal(city,street)` would select the `city` and
		                  `street` values inside the `postal` object inside the `address` object
		                  
		                  
		        * `features`
		        
		          Supports selecting arbitrary fields in features similar to `attributes` (see also Features documentation for more details)
		          
		        * `_namespace`
		        
		          Specifically selects the namespace also contained in the `thingId`
		          
		        * `_revision`
		        
		          Specifically selects the revision of the Thing. The revision is a counter, which is incremented on each modification of a Thing.
		          
		        * `_modified`
		        
		          Specifically selects the modified timestamp of the Thing in ISO-8601 UTC format. The timestamp is set on each modification of a Thing.
		          
		        * `_policy`
		        
		          Specifically selects the content of the policy associated to the thing. (By default, only the policyId is returned.)
		          
		        #### Examples
		        
		        * `?fields=thingId,attributes,features`
		        * `?fields=attributes(model,manufacturer),features`
		        
		      required: false
		      schema:
		        type: string
		    searchFilter:
		      name: filter
		      in: query
		      description: |-
		      
		        #### Filter predicates:
		        
		        * ```eq({property},{value})```  (i.e. equal to the given value)
		        
		        * ```ne({property},{value})```  (i.e. not equal to the given value)
		        
		        * ```gt({property},{value})```  (i.e. greater than the given value)
		        
		        * ```ge({property},{value})```  (i.e. equal to the given value or greater than it)
		        
		        * ```lt({property},{value})```  (i.e. lower than the given value or equal to it)
		        
		        * ```le({property},{value})```  (i.e. lower than the given value)
		        
		        * ```in({property},{value},{value},...)```  (i.e. contains at least one of the values listed)
		        
		        * ```like({property},{value})```  (i.e. contains values similar to the expressions listed)
		        
		        * ```exists({property})```  (i.e. all things in which the given path exists)
		        
		        
		        Note: When using filter operations, only things with the specified properties are returned.
		        For example, the filter `ne(attributes/owner, "SID123")` will only return things that do have
		        the `owner` attribute.
		        
		        #### Logical operations:
		        
		        * ```and({query},{query},...)```
		        
		        * ```or({query},{query},...)```
		        
		        * ```not({query})```
		        
		        
		        #### Examples:
		        
		        * ```eq(attributes/location,"kitchen")```
		        
		        * ```ge(thingId,"myThing1")```
		        
		        * ```exists(features/featureId)```
		        
		        * ```and(eq(attributes/location,"kitchen"),eq(attributes/color,"red"))```
		        
		        * ```or(eq(attributes/location,"kitchen"),eq(attributes/location,"living-room"))```
		        
		        * ```like(attributes/key1,"known-chars-at-start*")```
		        
		        * ```like(attributes/key1,"*known-chars-at-end")```
		        
		        * ```like(attributes/key1,"*known-chars-in-between*")```
		        
		        * ```like(attributes/key1,"just-som?-char?-unkn?wn")```
		        
		        The `like` filters with the wildcard `*` at the beginning can slow down your search request.
		      required: false
		      schema:
		        type: string
		    namespacesFilter:
		      name: namespaces
		      in: query
		      description: |-
		        A comma-separated list of namespaces. This list is used to limit the query to things in the given namespaces
		        only. If this parameter is omitted, all registered namespaces of your solution will be queried. The solution is
		        determined by the API token sent with the request.
		        
		        
		        #### Examples:
		        
		        * `?namespaces=com.example.namespace`
		        
		        * `?namespaces=com.example.namespace1,com.example.namespace2`
		      required: false
		      schema:
		        type: string
		    propertiesFieldsQueryParam:
		      name: fields
		      in: query
		      description: |-
		        Contains a comma-separated list of fields from the properties to be
		        included in the returned JSON.
		        
		        #### Selectable fields
		        
		        Supports selecting arbitrary sub-fields as defined in the properties by
		        using a comma-separated list:
		          * several properties paths can be passed as a comma-separated list of JSON pointers (RFC-6901)
		          
		            For example:
		              * `?fields=temperature` would select only `temperature` property value (if present)
		              * `?fields=temperature,humidity` would select only `temperature` and `humidity` property values (if present)
		              
		        Supports selecting arbitrary sub-fields of objects by wrapping sub-fields
		        inside parentheses `( )`:
		          * a comma-separated list of sub-fields (a sub-field is a JSON pointer (RFC-6901) separated with `/`) to select
		          * sub-selectors can be used to request only specific sub-fields by placing expressions in parentheses `( )` after a selected subfield
		          
		            For example:
		             * `?fields=location(longitude,latitude)` would select the `longitude` and `latitude` value inside the `location` property
		             
		        #### Examples
		        
		        * `?fields=temperature,humidity,location(longitude,latitude)`
		        
		        * `?fields=configuration,status(powerConsumption/watts)`
		      required: false
		      schema:
		        type: string
		    featuresFieldsQueryParam:
		      name: fields
		      in: query
		      description: |-
		        Contains a comma-separated list of fields from one or more Features to be
		        included in the returned JSON.
		        
		        #### Selectable fields
		        
		        * `{featureId}` The ID of the Feature to select properties in
		          * `properties`
		            Supports selecting arbitrary sub-fields by using a comma-separated list:
		              * several properties paths can be passed as a comma-separated list of JSON pointers (RFC-6901)
		                For example:
		                  * `?fields={featureId}/properties/color` would select only `color` property value (if present) of the Feature identified with `{featureId}`
		                  * `?fields={featureId}/properties/color,properties/brightness` would select only `color` and `brightness` property values (if present) of the Feature identified with `{featureId}`
		            Supports selecting arbitrary sub-fields of objects by wrapping sub-fields inside parentheses `( )`:
		              * a comma-separated list of sub-fields (a sub-field is a JSON pointer (RFC-6901) separated with `/`) to select
		              * sub-selectors can be used to request only specific sub-fields by placing expressions in parentheses `( )` after a selected subfield
		                For example:
		                 * `?fields={featureId}/properties(color,brightness)` would select only `color` and `brightness` property values (if present) of the Feature identified with `{featureId}`
		                 * `?fields={featureId}/properties(location/longitude)` would select the `longitude` value inside the `location` object of the Feature identified with `{featureId}`
		                 
		                 
		        #### Examples
		        * `?fields=EnvironmentScanner/properties(temperature,humidity)`
		        * `?fields=EnvironmentScanner/properties(temperature,humidity),Vehicle/properties/configuration`
		      required: false
		      schema:
		        type: string
		    featureFieldsQueryParam:
		      name: fields
		      in: query
		      description: |-
		        Contains a comma-separated list of fields from the selected Feature to be
		        included in the returned JSON.
		  
		        #### Selectable fields
		  
		        * `properties`
		  
		          Supports selecting arbitrary sub-fields by using a comma-separated list:
		            * several properties paths can be passed as a comma-separated list of JSON pointers (RFC-6901)
		  
		              For example:
		                * `?fields=properties/color` would select only `color` property value (if present)
		                * `?fields=properties/color,properties/brightness` would select only `color` and `brightness` property values (if present)
		  
		          Supports selecting arbitrary sub-fields of objects by wrapping sub-fields inside parentheses `( )`:
		            * a comma-separated list of sub-fields (a sub-field is a JSON pointer (RFC-6901) separated with `/`) to select
		            * sub-selectors can be used to request only specific sub-fields by placing expressions in parentheses `( )` after a selected subfield
		  
		              For example:
		               * `?fields=properties(color,brightness)` would select only `color` and `brightness` property values (if present)
		               * `?fields=properties(location/longitude)` would select the `longitude` value inside the `location` object
		  
		        #### Examples
		  
		        * `?fields=properties(color,brightness)`
		      required: false
		      schema:
		        type: string
		  securitySchemes:
		    bearerAuth:
		      type: http
		      scheme: bearer
		      bearerFormat: JWT
		      description: |-
		        A JSON Web Token issued by a supported OAuth 2.0 Identity Provider.
		'''
	}
		
	/*
	 * Checks if the information has elements that requires request body to be set
	 */
	def hasRequestBodiesContent(InformationModel infomodel) {
		var boolean flag = false;
		
		for (FunctionblockModel fb : Utils.getReferencedFunctionBlocks(infomodel)) {
			for (Event event : fb.functionblock.events) {
				if (!event.properties.empty) {
					flag = true;
				}
			}
			
			if (fb.functionblock.configuration !== null && !fb.functionblock.configuration.properties.empty) {
				flag = true;
			}
			
			for (Operation operation : fb.functionblock.operations) {
				if (!operation.params.isEmpty) {
					flag = true;
				}
			}
		}
		return flag;
	}
	
	def handleConstraints(ConstraintRule rule) {
	'''
	«FOR constraint : rule.constraints»
	«getConstraint(constraint.type)»«constraint.constraintValues»
	«IF constraint.type == ConstraintIntervalType.MAX»
	example: «constraint.constraintValues»
	«ENDIF»
	«ENDFOR»
	'''
	}
		
	def wrapIfMultiple(String type, boolean isArray) {
		'''
		«IF isArray»
		type: array
		items:
		  «type»
		«ELSE»
		«type»
		«ENDIF»
		'''
	}
	
	def getPrimitive(PrimitiveType primitiveType) {
		'''
		«IF primitiveType == PrimitiveType.BASE64_BINARY»
		type: string
		«ELSEIF primitiveType == PrimitiveType.BOOLEAN»
		type: boolean
		«ELSEIF primitiveType == PrimitiveType.BYTE»
		type: string
		«ELSEIF primitiveType == PrimitiveType.DATETIME»
		type: string
		«ELSEIF primitiveType == PrimitiveType.DOUBLE»
		type: number
		«ELSEIF primitiveType == PrimitiveType.FLOAT»
		type: number
		«ELSEIF primitiveType == PrimitiveType.INT»
		type: integer
		«ELSEIF primitiveType == PrimitiveType.LONG»
		type: number
		«ELSEIF primitiveType == PrimitiveType.SHORT»
		type: integer
		«ELSE»
		type: string
		«ENDIF»
		'''
	}
	
	def getConstraint(ConstraintIntervalType type) {
		if(type == ConstraintIntervalType.STRLEN){
			return '''maxLength: '''
		} else if(type == ConstraintIntervalType.REGEX) {
			return '''pattern: '''
		} else if(type == ConstraintIntervalType.MIN) {
			return '''minimum: '''
		} else if(type == ConstraintIntervalType.MAX) {
			return '''maximum: '''
		} else if(type == ConstraintIntervalType.SCALING) {
			return '''multipleOf: '''
		} else if(type == ConstraintIntervalType.DEFAULT) {
			return '''default: '''
		}
		
		return null
	}	
	
}
